package graph.tests;

import java.util.*;

import junit.framework.*;
import graph.*;

public abstract class IGraphAbstractTest extends TestCase {

    private IGraph graph;
    private final static String A = "A";
    private final static String B = "B";
    private final static String C = "C";
    private final static String D = "D";
    private final static String E = "E";

    protected final static int VERTICES_NUMBER = 5;

    public IGraphAbstractTest(String s) {
        super(s);
    }

    protected void setUp(IGraph graph) {
        this.graph = graph;
        graph.addVertex(A);
        graph.addVertex(B);
        graph.addVertex(C);
        graph.addVertex(D);
        graph.addVertex(E);
        graph.addEdge(A, B, 5);
        graph.addEdge(B, C, 4);
        graph.addEdge(C, D, 8);
        graph.addEdge(D, C, 8);
        graph.addEdge(D, E, 6);
        graph.addEdge(A, D, 5);
        graph.addEdge(C, E, 2);
        graph.addEdge(E, B, 3);
        graph.addEdge(A, E, 7);
    }

    protected void tearDown() {
    }

    public void testGetVerticesNumber() {
        assertEquals(VERTICES_NUMBER, graph.getVerticesNumber());
    }

    public void testAddVertex() {
        try {
            graph.addVertex("Z");
            fail("Should raise an Exception");
        } catch (Exception e) { System.out.println(e.toString()); }
    }

    public void testAddEdge() {
        try {
            graph.addEdge("Z", B, 5);
            fail("Should raise an Exception");
        } catch (Exception e) { System.out.println(e.toString()); }

        try {
            graph.addEdge(A, "Z", 5);
            fail("Should raise an Exception");
        } catch (Exception e) { System.out.println(e.toString()); }
        try {
            graph.addEdge(A, B, 0);
            fail("Should raise an Exception");
        } catch (Exception e) { System.out.println(e.toString()); }
    }

    public void testRemoveEdge() {
        graph.addEdge(A, C, 1);
        graph.removeEdge(A, C);
        assertTrue(!graph.edgeExist(A, C));
    }

    public void testVertexExist() {
        assertTrue(graph.vertexExist(A));
        assertTrue(graph.vertexExist(B));
        assertTrue(graph.vertexExist(C));
        assertTrue(graph.vertexExist(D));
        assertTrue(graph.vertexExist(E));
        assertTrue(!graph.vertexExist("Z"));
    }

    public void testEdgeExist() {
        // tests with edges wich exist
        assertTrue(graph.edgeExist(A, B));
        assertTrue(graph.edgeExist(B, C));

        // This edge does not exist
        assertTrue(!graph.edgeExist(A,C));
    }

    public void testGetEdgeWeight() {
        assertEquals(5, graph.getEdgeWeight(A, B));
        assertEquals(4, graph.getEdgeWeight(B, C));

        // if the edge does not exist, the weight is 0
        assertEquals(0, graph.getEdgeWeight(A, C));
    }

    public void testGetEdgeWeight_Path() {
        Path p1 = new Path();
        p1.addVertex(A).addVertex(B).addVertex(C);
        assertEquals(9, graph.getEdgeWeight(p1) );

        Path p2 = new Path();
        p2.addVertex(A).addVertex(D);
        assertEquals(5, graph.getEdgeWeight(p2));

        Path p3 = new Path();
        p3.addVertex(A).addVertex(D).addVertex(C);
        assertEquals(13, graph.getEdgeWeight(p3));

        Path p4 = new Path();
        p4.addVertex(A).addVertex(E).addVertex(B).addVertex(C).addVertex(D);
        assertEquals(22, graph.getEdgeWeight(p4));

        Path p5 = new Path();
        p5.addVertex(A).addVertex(E).addVertex(D);
        String[] a5 = {A, E, D};
        assertEquals(0, graph.getEdgeWeight(p5));
    }

    public void testGetAdjacentVertices() {
        String[] arrayA = {B, D, E};
        testIfAllArePresent( graph.getAdjacentVertices(A), Arrays.asList(arrayA) );

        String[] arrayB = {C};
        testIfAllArePresent( graph.getAdjacentVertices(B), Arrays.asList(arrayB) );

        String[] arrayC = {D, E};
        testIfAllArePresent( graph.getAdjacentVertices(C), Arrays.asList(arrayC) );

        String[] arrayD = {C};
        testIfAllArePresent( graph.getAdjacentVertices(D), Arrays.asList(arrayD) );

        String[] arrayE = {B};
        testIfAllArePresent( graph.getAdjacentVertices(E), Arrays.asList(arrayE) );
    }

    public void testGetPredecessors() {
        String[] arrayA = {};
        testIfAllArePresent( graph.getPredecessors(A), Arrays.asList(arrayA) );

        String[] arrayB = {A, E};
        testIfAllArePresent( graph.getPredecessors(B), Arrays.asList(arrayB) );

        String[] arrayC = {B, D};
        testIfAllArePresent( graph.getPredecessors(C), Arrays.asList(arrayC) );

        String[] arrayD = {A, C};
        testIfAllArePresent( graph.getPredecessors(D), Arrays.asList(arrayD) );

        String[] arrayE = {A, C, D};
        testIfAllArePresent( graph.getPredecessors(E), Arrays.asList(arrayD) );
    }

    private void testIfAllArePresent(Iterator iter, List list) {
        Vector vertices = new Vector(list);
        while (iter.hasNext()) {
            Object item = iter.next();
            if (vertices.contains(item)) {
                vertices.remove(item);
            }
        }
        // the list should be empty if the test is a success (all the adjacents vertices are present)
        Assert.assertTrue(vertices.isEmpty());
    }
}
